package com.platform.user.controller;

import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.platform.bean.JwtProperties;
import com.platform.bean.Result;
import com.platform.exception.BaseException;
import com.platform.user.entity.MyAdminDetails;
import com.platform.user.entity.MyUserDetails;
import com.platform.user.service.MyAdminDetailService;
import com.platform.user.service.MyUserDetailService;
import com.platform.user.service.OnlineService;
import com.platform.utils.JwtTokenUtils;
import com.platform.utils.RedisUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/auth")
public class  AuthController {

    @Resource
    private DefaultKaptcha defaultKaptcha;
    @Resource
    private JwtTokenUtils jwtTokenUtils;
    @Resource
    private PasswordEncoder passwordEncoder;
    @Resource
    private JwtProperties jwtProperties;
    @Resource
    private MyAdminDetailService myAdminDetailService;
    @Resource
    private MyUserDetailService myUserDetailService;
    @Resource
    private RedisUtils redisUtils;
    @Resource
    private OnlineService onlineService;

    private final static String VERIFICATION_CODE_KEY = "verification-code-key:";

    @PostMapping("/userLogin")
    public Result userLogin(@RequestBody Map<String, Object> params) {
        String username = (String) params.get("username");
        String password = (String) params.get("password");
        String verificationCode = (String) params.get("verificationCode");
        String verificationCodeKey = (String) params.get("verificationCodeKey");
        Map<String, Object> errorDetails = new HashMap<>();

        String code = (String) redisUtils.get(verificationCodeKey);
        if (code == null) {
            errorDetails.put("msg", "验证码过期");
            errorDetails.put("status", 0);
            return Result.fail(errorDetails);
        } else {
            if (!code.equals(verificationCode)) {
                errorDetails.put("msg", "验证码错误");
                errorDetails.put("status", 0);
                return Result.fail(errorDetails);
            }
        }

        MyUserDetails myUserDetails = (MyUserDetails) myUserDetailService.loadUserByUsername(username);
        // MyAdminDetails adminDetails = (MyAdminDetails) myAdminDetailService.loadUserByUsername(username);

        if (myUserDetails == null) {
            errorDetails.put("msg", "用户不存在");
            errorDetails.put("status", 0);
            return Result.fail(errorDetails);
        }

        if (!passwordEncoder.matches(password, myUserDetails.getPassword())) {
            errorDetails.put("msg", "用户名或密码错误");
            errorDetails.put("status", 0);
            return Result.fail(errorDetails);
        }

        Authentication authentication = new UsernamePasswordAuthenticationToken(myUserDetails,
                myUserDetails.getPassword(), myUserDetails.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authentication);
        String jwt = jwtTokenUtils.generateToken(authentication);
        System.out.println("生成的token:" + jwtProperties.getTokenStartWith() + jwt);

        onlineService.saveUser(myUserDetails.getUser(), jwt);

        Map<String, Object> result = new HashMap<>(9);
        Map<String, Object> userInfo = new HashMap<>();

        userInfo.put("username", myUserDetails.getUser().getUsername());
        userInfo.put("id", myUserDetails.getUser().getId());
        userInfo.put("fullName", myUserDetails.getUser().getFullName());
        userInfo.put("identity", myUserDetails.getUser().getIdentity());
        userInfo.put("academy", myUserDetails.getUser().getAcademy());
        userInfo.put("major", myUserDetails.getUser().getMajor());
        userInfo.put("email", myUserDetails.getUser().getEmail());

        result.put("token", jwtProperties.getTokenStartWith() + jwt);
        result.put("uid",  myUserDetails.getUser().getId());
        result.put("msg", "登录成功");
        result.put("status", 1);
        result.put("userRole", 0);
        result.put("userInfo", userInfo);

        return Result.ok(result);
    }

    @PostMapping("/adminLogin")
    public Result adminLogin(@RequestBody Map<String, Object> params) {
        String username = (String) params.get("username");
        String password = (String) params.get("password");
        String verificationCode = (String) params.get("verificationCode");
        String verificationCodeKey = (String) params.get("verificationCodeKey");
        Map<String, Object> errorDetails = new HashMap<>();

        String code = (String) redisUtils.get(verificationCodeKey);
        if (code == null) {
            errorDetails.put("msg", "验证码过期");
            errorDetails.put("status", 0);
            return Result.fail(errorDetails);
        } else {
            if (!code.equals(verificationCode)) {
                errorDetails.put("msg", "验证码错误");
                errorDetails.put("status", 0);
                return Result.fail(errorDetails);
            }
        }

        MyAdminDetails adminDetails = (MyAdminDetails) myAdminDetailService.loadUserByUsername(username);

        if (adminDetails == null) {
            errorDetails.put("msg", "用户不存在");
            errorDetails.put("status", 0);
            return Result.fail(errorDetails);
        }

        if (!passwordEncoder.matches(password, adminDetails.getPassword())) {
            errorDetails.put("msg", "用户名或密码错误");
            errorDetails.put("status", 0);
            return Result.fail(errorDetails);
        }
        Authentication authentication = new UsernamePasswordAuthenticationToken(adminDetails,
                adminDetails.getPassword(), adminDetails.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authentication);
        String jwt = jwtTokenUtils.generateToken(authentication);
        System.out.println("生成的token:" + jwtProperties.getTokenStartWith() + jwt);

        onlineService.saveAdmin(adminDetails.getAdmin(), jwt);

        Map<String, Object> result = new HashMap<>(9);
        Map<String, Object> userInfo = new HashMap<>();

        userInfo.put("username", adminDetails.getAdmin().getUsername());
        userInfo.put("id", adminDetails.getAdmin().getId());
        userInfo.put("fullName", adminDetails.getAdmin().getFullName());
        userInfo.put("identity", adminDetails.getAdmin().getIdentity());
        userInfo.put("academy", adminDetails.getAdmin().getAcademy());
        userInfo.put("major", adminDetails.getAdmin().getMajor());
        userInfo.put("email", adminDetails.getAdmin().getEmail());

        result.put("token", jwtProperties.getTokenStartWith() + jwt);
        result.put("aid", adminDetails.getAdmin().getId());
        result.put("msg", "登录成功");
        result.put("status", 1);
        result.put("userRole", 1);
        result.put("userInfo", userInfo);

        return Result.ok(result);
    }

    @GetMapping("/getCaptchaImage")
    public Result getCaptchaImage(@RequestParam(name = "verificationCodeKey", required = false) String key) throws IOException {
        StringBuilder sb = new StringBuilder();
        String text = defaultKaptcha.createText();
        BufferedImage image = defaultKaptcha.createImage(text);
        String verificationCodeKey = sb.append(VERIFICATION_CODE_KEY)
                .append(System.currentTimeMillis()).toString();
        if (key != null) {
            redisUtils.del(key);
        }
        redisUtils.set(verificationCodeKey, text, 600, TimeUnit.SECONDS);

        //session.setAttribute("kaptcha", text);
        byte[] imageBytes;
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(image, "png", baos);
            imageBytes = baos.toByteArray();
        } catch (IOException e) {
            throw new BaseException("响应验证码失败:" + e.getMessage());
        }

        Map<String, Object> res = new HashMap<>();
        res.put("code", Base64.getEncoder().encodeToString(imageBytes));
        res.put("key", verificationCodeKey);
        return Result.ok(res);
    }
}
